<!DOCTYPE html>
<html>
<head>
    <!-- BEGIN:X3DOM -->
    <meta http-equiv="X-UA-Compatible" content="chrome=1,IE=edge"/>
    <link rel="stylesheet" type="text/css" href="../../src/x3dom.css"/>
    <script type="text/javascript" src="../../src/lang/Array.js"></script>
    <script type="text/javascript" src="../../src/Internals.js"></script>
    <script type="text/javascript" src="../../src/debug.js"></script>
    <script type="text/javascript" src="../../src/util/AdaptiveRenderControl.js"></script>
    <script type="text/javascript" src="../../src/util/DownloadManager.js"></script>
    <script type="text/javascript" src="../../src/util/Properties.js"></script>
    <script type="text/javascript" src="../../src/util/DoublyLinkedList.js"></script>
    <script type="text/javascript" src="../../src/util/EarClipping.js"></script>
    <script type="text/javascript" src="../../src/util/Utils.js"></script>
    <script type="text/javascript" src="../../src/util/States.js"></script>
    <script type="text/javascript" src="../../src/util/StateManager.js"></script>
    <script type="text/javascript" src="../../src/util/BinaryContainerSetup.js"></script>
    <script type="text/javascript" src="../../src/util/DrawableCollection.js"></script>
    <script type="text/javascript" src="../../src/X3DCanvas.js"></script>
    <script type="text/javascript" src="../../src/Runtime.js"></script>
    <script type="text/javascript" src="../../src/Main.js"></script>
    <script type="text/javascript" src="../../src/Cache.js"></script>
    <script type="text/javascript" src="../../src/Texture.js"></script>
    <script type="text/javascript" src="../../src/shader/Shader.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderParts.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderDynamic.js"></script>
	<script type="text/javascript" src="../../src/shader/ShaderDynamicPicking.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderComposed.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderNormal.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderFrontgroundTexture.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderBackgroundTexture.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderBackgroundSkyTexture.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderBackgroundCubeTexture.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderShadow.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderShadowRendering.js"></script>
    <script type="text/javascript" src="../../src/shader/ShaderBlur.js"></script>
    <script type="text/javascript" src="../../src/gfx_webgl.js"></script>
    <script type="text/javascript" src="../../src/gfx_flash.js"></script>
    <script type="text/javascript" src="../../src/X3DDocument.js"></script>
    <script type="text/javascript" src="../../src/MatrixMixer.js"></script>
    <script type="text/javascript" src="../../src/Viewarea.js"></script>
    <script type="text/javascript" src="../../src/Mesh.js"></script>
    <script type="text/javascript" src="../../src/fields.js"></script>
    <script type="text/javascript" src="../../src/NodeNameSpace.js"></script>
    <script type="text/javascript" src="../../src/nodes/Core.js"></script>
    <script type="text/javascript" src="../../src/nodes/Grouping.js"></script>
    <script type="text/javascript" src="../../src/Bindable.js"></script>
    <script type="text/javascript" src="../../src/nodes/Rendering.js"></script>
    <script type="text/javascript" src="../../src/nodes/Shape.js"></script>
    <script type="text/javascript" src="../../src/nodes/Lighting.js"></script>
    <script type="text/javascript" src="../../src/nodes/Followers.js"></script>
    <script type="text/javascript" src="../../src/nodes/Interpolation.js"></script>
    <script type="text/javascript" src="../../src/nodes/Time.js"></script>
    <script type="text/javascript" src="../../src/nodes/Networking.js"></script>
    <script type="text/javascript" src="../../src/nodes/EnvironmentalEffects.js"></script>
    <script type="text/javascript" src="../../src/nodes/Navigation.js"></script>
    <script type="text/javascript" src="../../src/nodes/Text.js"></script>
    <script type="text/javascript" src="../../src/nodes/Sound.js"></script>
    <script type="text/javascript" src="../../src/nodes/Texturing.js"></script>
    <script type="text/javascript" src="../../src/nodes/Shaders.js"></script>
    <script type="text/javascript" src="../../src/nodes/Geometry3D.js"></script>
    <script type="text/javascript" src="../../src/nodes/Texturing3D.js"></script>
    <script type="text/javascript" src="../../src/nodes/Geospatial.js"></script>
    <script type="text/javascript" src="../../src/nodes/Geometry2D.js"></script>
    <script type="text/javascript" src="../../src/nodes/VolumeRendering.js"></script>
    <script type="text/javascript" src="../../src/nodes/CADGeometry.js"></script>
    <script type="text/javascript" src="../../src/nodes/BVHRefiner.js"></script>
    <script type="text/javascript" src="../../src/nodes/Geometry3DExt.js"></script>
    <script type="text/javascript" src="../../src/util/Moveable.js"></script>
    <script type="text/javascript" src="../../src/Docs.js"></script>
    <!-- END:X3DOM -->

    <script type="text/javascript" src="JSARToolKit.js"></script>

    <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
    <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
    <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>

    <style>
        .x3dom-nox3d {
            position: absolute;
            top: 240px;
            left: 140px;
        }

        .ar {
            background-color: #ffbfa7;
            width: 640px;
            height: 480px;
            border: 1px solid #000;
        }

        .state {
            margin-top: 10px;
            margin-bottom: 10px;
        }

        #status {
            font-size: x-large;
        }

        #btns {
            font-size: large;
        }

        #slider {
            margin: 10px;
            width: 620px;
        }

        .left {
            margin-left: 10px;
            z-index: 1;
        }

        #trackerCanvas {
            position: absolute;
            top: 8px;
            left: 680px;
            border: 1px solid red;
        }

        #debugCanvas {
            position: absolute;
            top: 248px;
            left: 680px;
            border: 1px solid red;
        }

        #container {
            position: absolute;
            top: 8px;
        }
    </style>
<body>
    <div class="ar">
        <canvas id="bgnd" width="640px" height="480px"></canvas>
    </div>

    <div id='container'>
        <X3D id="x3d" showStat='true' showLog='true' width="640px" height="480px">
            <Scene>
                <Viewfrustum id="vf"></Viewfrustum>

                <MatrixTransform id="root">
                    <Transform rotation="0 1 0 3.14159265359">
                        <Transform rotation="0 0 1 3.14159265359">
                            <Shape>
                                <Appearance>
                                    <Material diffuseColor=".7 .5 .2" specularColor=".2 .2 .2"></Material>
                                    <ImageTexture url="../functional/media/texture/snaefari.jpg"></ImageTexture>
                                </Appearance>
                                <Plane size="120 120"></Plane>
                            </Shape>
                            <Shape>
                                <Appearance>
                                    <LineProperties linewidthScaleFactor="2"></LineProperties>
                                </Appearance>
                                <IndexedLineSet DEF="cs" coordIndex="0 1 -1, 2 3 -1, 4 5 -1">
                                    <Coordinate point="100 0 0, 0 0 0, 0 100 0, 0 0 0, 0 0 100, 0 0 0"></Coordinate>
                                    <Color color="1 0 0, 1 0 0, 0 1 0, 0 1 0, 0 0 1, 0 0 1"></Color>
                                </IndexedLineSet>
                            </Shape>
                        </Transform>
                    </Transform>
                </MatrixTransform>
            </Scene>
        </X3D>
    </div>

    <div class="state">
        <span id="status">Not tracking...</span>
        <br>
        <span>Marker Tracker: <a href="https://github.com/kig/JSARToolKit">JSARToolKit.js</a></span>
    </div>

    <div class="state">
        <div id="btns">
            <input class="left" type="button" value="Show marker image" onclick="showMarker();">
            <input class="left" type="button" id="btnTrack" value="Stop tracking" onclick="toggleTracking();">
            <span class="left"> Binarization threshold: <span id="threshold">128</span></span>
        </div>
        <div id="slider"></div>
    </div>

    <script>
        // CAMERA_BASED TRACKING STUFF
        window.URL = window.URL || window.webkitURL;

        DEBUG = true;

        var runtime = null;
        var root = null;

        var initDone = false;
        var doTracking = true;

        var width = 320;
        var height = 240;

        var canvas = null;
        var videoCanvas = null;

        var detector = null;
        var raster = null;

        var resultMat = null;
        var threshold = 100; //128;

        document.getElementById("threshold").innerHTML = threshold;

        $("#slider").slider({ min:0, max: 255, value: threshold });

        $("#slider").on( "slide", function( event, ui ) {
            threshold = ui.value;
            document.getElementById("threshold").innerHTML = threshold;
        } );

        // Using getUserMedia to access the webcam
        var videoStream = null;

        var video = document.createElement('video');

        video.width = width;
        video.height = height;
        video.loop = true;
        video.autoplay = true;
        video.controls = true;
        video.volume = 0;
        video.style.display = 'none';

        var getUserMedia = function(t, onsuccess, onerror) {
            if (navigator.getUserMedia) {
                return navigator.getUserMedia(t, onsuccess, onerror);
            } else if (navigator.webkitGetUserMedia) {
                return navigator.webkitGetUserMedia(t, onsuccess, onerror);
            } else if (navigator.mozGetUserMedia) {
                return navigator.mozGetUserMedia(t, onsuccess, onerror);
            } else if (navigator.msGetUserMedia) {
                return navigator.msGetUserMedia(t, onsuccess, onerror);
            } else {
                onerror(new Error("No getUserMedia implementation found."));
                return null;
            }
        };

        var createObjectURL = window.URL.createObjectURL;

        if (!createObjectURL) {
            throw new Error("URL.createObjectURL not found.");
        }

        function startCam() {
            getUserMedia(
                {video: true, audio: false},
                function(stream) {
                    video.crossOrigin = "";
                    video.src = createObjectURL(stream);
                    videoStream = stream;
                },
                function(error) {
                    alert("Could not access webcam.");
                });
        }
        startCam();


        document.onload = function()
        {
            runtime = document.getElementById("x3d").runtime;

            root = document.getElementById("root");

            runtime.exitFrame = function () {
                if (!initDone) {
                    initializeTracker();
                    initDone = true;
                }

                if (doTracking) {
                    animate();
                    this.triggerRedraw();
                }
            };
        };

        function toggleTracking()
        {
            var btn = document.getElementById("btnTrack");

            doTracking = !doTracking;

            if (!doTracking) {
                document.getElementById("status").innerHTML = "Not tracking...";
                btn.value = "Start tracking";

                video.pause();
                video.src = "";
                videoStream.stop();
                videoStream = null;
            }
            else {
                startCam();

                btn.value = "Stop tracking";
                runtime.triggerRedraw();
            }
        }

        function redraw()
        {
            videoCanvas.getContext('2d').drawImage(video, 0, 0);
            canvas.getContext('2d').drawImage(videoCanvas, 0, 0, width, height);

            // Tell JSARToolKit that the canvas has changed.
            canvas.changed = true;
        }

        function animate()
        {
            // Draw the video frame to the canvas.
            try {
                redraw();
            }
            catch (e) {
                // workaround for Firefox
                if (e.name == "NS_ERROR_NOT_AVAILABLE") {
                    setTimeout(function() { redraw(); }, 10);
                }
                else { throw e; }
            }

            // Detect the markers in the video frame.
            var markerCount = detector.detectMarkerLite(raster, threshold);

            for (var i=0; i<markerCount; i++) {
                // Get the marker matrix into the result matrix.
                detector.getTransformMatrix(i, resultMat);

                // Copy the marker matrix to the tmp matrix.
                var tmpMat = adaptMarkerMatrix(resultMat);

                // Copy the marker matrix over to your marker root object.
                root.setAttribute("matrix", tmpMat.toGL().toString());
            }

            if (markerCount > 0 ) {
                document.getElementById("status").innerHTML = "Tracking " + markerCount + " marker"
            }
            else {
                document.getElementById("status").innerHTML = "Not tracking..."
            }
        }

        function adaptMarkerMatrix(arMat)
        {
            var tmpMat = new x3dom.fields.SFMatrix4f(
                         arMat.m00,  arMat.m01,  arMat.m02,  arMat.m03,
                         arMat.m10,  arMat.m11,  arMat.m12,  arMat.m13,
                         arMat.m20,  arMat.m21,  arMat.m22,  arMat.m23,
                                 0,          0,          0,          1);

            var translation = new x3dom.fields.SFVec3f(0,0,0),
                scale = new x3dom.fields.SFVec3f(1,1,1);
            var rotation = new x3dom.fields.Quaternion(0,0,1,0),
                scaleOrient = new x3dom.fields.Quaternion(0,0,1,0);

            tmpMat.getTransform(translation, rotation, scale, scaleOrient);

            rotation.y *= -1;
            rotation.z *= -1;
            translation.y *= -1;
            translation.z *= -1;

            tmpMat = rotation.toMatrix();
            tmpMat.setTranslate(translation);

            return tmpMat;
        }

        function initializeTracker()
        {
            // Setting up JSARToolKit
            canvas = document.createElement('canvas');
            canvas.id = "trackerCanvas";
            canvas.width = width;
            canvas.height = height;
            document.body.appendChild(canvas);

            if (DEBUG) {
                var debugCanvas = document.createElement('canvas');
                debugCanvas.id = 'debugCanvas';
                debugCanvas.width = width;
                debugCanvas.height = height;
                document.body.appendChild(debugCanvas);
            }

            // Create an RGB raster object for the 2D canvas.
            // JSARToolKit uses raster objects to read image data.
            // Note that you need to set canvas.changed = true on every frame.
            raster = new NyARRgbRaster_Canvas2D(canvas);

            // FLARParam is the thing used by FLARToolKit to set camera parameters.
            // Here we create a FLARParam for images with 320x240 pixel dimensions.
            var param = new FLARParam(width, height);

            // The FLARMultiIdMarkerDetector is the actual detection engine for marker detection.
            // It detects multiple ID markers. ID markers are special markers that encode a number.
            detector = new FLARMultiIdMarkerDetector(param, 120);

            // For tracking video set continue mode to true. In continue mode, the detector
            // tracks markers across multiple frames.
            detector.setContinueMode(true);


            // Copy the camera perspective matrix from the FLARParam to the WebGL library camera matrix.
            // The second and third parameters determine the zNear and zFar planes for the perspective matrix.
            var camera = document.getElementById("vf");

            var zNear = camera.getNear();
            var zFar = camera.getFar();
            var perspectiveMatrix = runtime.projectionMatrix().toGL();

            param.copyCameraMatrix(perspectiveMatrix, zNear, zFar);

            var proj = new x3dom.fields.SFMatrix4f();
            proj.setFromArray(perspectiveMatrix);
            proj._22 *= -1;
            proj._32 *= -1;

            camera.setAttribute("projection", proj.toGL().toString());


            // Detecting markers
            videoCanvas = document.getElementById('bgnd');

            // Draw the video frame to the raster canvas, scaled to 320x240.
            // And tell the raster object that the underlying canvas has changed.
            redraw();

            // Do marker detection by using the detector object on the raster object.
            // The threshold parameter determines the threshold value
            // for turning the video frame into a 1-bit black-and-white image.
            var markerCount = detector.detectMarkerLite(raster, threshold);

            // Create a NyARTransMatResult object for getting the marker translation matrices.
            resultMat = new NyARTransMatResult();

            var markers = {};

            // Go through the detected markers and get their IDs and transformation matrices.
            for (var idx = 0; idx < markerCount; idx++) {
                // Get the ID marker data for the current marker.
                // ID markers are special kind of markers that encode a number.
                // The bytes for the number are in the ID marker data.
                var id = detector.getIdMarkerData(idx);

                // Read bytes from the id packet.
                var currId = -1;
                // This code handles only 32-bit numbers or shorter.
                if (id.packetLength <= 4) {
                    currId = 0;
                    for (var i = 0; i < id.packetLength; i++) {
                        currId = (currId << 8) | id.getPacketData(i);
                    }

                    // If this is a new id, let's start tracking it.
                    if (markers[currId] == null) {
                        markers[currId] = {};
                    }
                    // Get the transformation matrix for the detected marker.
                    detector.getTransformMatrix(idx, resultMat);

                    // Copy the result matrix into our marker tracker object.
                    markers[currId].transform = Object.asCopy(resultMat);
                }
            }
        }

        function showMarker()
        {
            var win = window.open('./marker.png','Marker','width=420,height=420');
            win.focus();
        }
    </script>
</body>
</html>